package users

import (
	"fmt"
	"go-demo-2025/common"
	"go-demo-2025/utils/excelUtils"
	"go-demo-2025/utils/funcUtils"
	"math"
	"os"
	"path/filepath"
	"strconv"
)

// 通过反射直接获取结构体中的所有数据字段,并转换为map,再根据key的顺序逐一映射到新的切片.推荐!
func (ctx *UserService) ExportUserList() {
	requestKey := common.GetYmdHis() + "_" + common.RandomString(10)
	count := ctx.GetUserCount()

	//分页查询列表
	pageSize := 1000                                           //每页查询多少条
	pageCount := math.Ceil(float64(count) / float64(pageSize)) //总页数
	//fmt.Println("总页数:", pageCount)

	//自定义导出的字段
	var dataKeySlice [][]string
	//如果需要导出数据表的所有字段,则注释下面的二维切片
	dataKeySlice = [][]string{
		{"id", "ID"},
		{"user_id", "用户ID"},
		{"name", "用户姓名"},
		{"age", "年龄"},
		{"address", "地址"},
		{"create_time", "添加时间"},
	}
	dataKeys, dataKeysTitle := excelUtils.GetDataKeyAndTitle(dataKeySlice)

	for page := 1; page <= int(pageCount); page++ {
		dataList := ctx.GetUserList(page, pageSize)

		var excelData [][]string
		for key, item := range dataList {
			//如果没有定义指定要导出的字段,则获取数据表的所有字段
			if len(dataKeys) == 0 { //dataKeys切片(model结构体的tag的json部分)
				dataKeys = funcUtils.GetStructTag(item)
			}

			//结构体转为map
			itemMap, _ := funcUtils.StructToMap(item, "json")
			//fmt.Println(itemMap)
			//os.Exit(1)

			//按照顺序将map中的数据填充到key的切片中
			var itemSlice []string
			//第一列使用key,下一步排序用
			itemSlice = append(itemSlice, fmt.Sprintf("%03d", key)) //key前面补两个0,要不然反转的时候会按照字符串顺序排序,导致"2>10".这样改后就是"10>02")
			for _, keys := range dataKeys {                         //按照dataKeys设定的字段,逐一插入到切片中
				itemSlice = append(itemSlice, itemMap[keys])
			}
			excelData = append(excelData, itemSlice)
		}

		funcUtils.ReverseTwoDimSlice(excelData)                     //倒序排列,必须保证第0个元素是 key 值
		excelData = funcUtils.DeleteTwoDimSliceFirstChar(excelData) //删除第0个元素(key值)
		pageDiff := int(pageCount) - page + 1

		//导出Excel文件
		_, err1 := excelUtils.WriteExcel(excelData, requestKey, fmt.Sprintf("用户数据导出_page_%s", fmt.Sprintf("%04d", pageDiff)))
		if err1 != nil {
			fmt.Println("Write excel error: ", err1)
			os.Exit(1)
		}
		//fmt.Println("Write excel success, file name is: ", fileName)
	}

	//导出表头
	var excelDataTitle [][]string
	if len(dataKeysTitle) == 0 {
		dataKeysTitle = dataKeys
	}
	excelDataTitle = append(excelDataTitle, dataKeysTitle)
	fileName, _ := excelUtils.WriteExcel(excelDataTitle, requestKey, "用户数据导出_page_0000")

	//合并多个文件为一个
	absPath, _ := filepath.Abs(fileName) // 获取文件的绝对路径
	dirPath := filepath.Dir(absPath)     //获取文件所在目录的绝对路径
	//fmt.Println(dirPath)
	outputFileName := fmt.Sprintf("用户数据导出_%v.xlsx", requestKey)
	outputFilePath := excelUtils.MergeExcel(dirPath, outputFileName, true)
	fmt.Println("最终导出的文件:", outputFilePath)
}

// 通过切片形式导出Excel,需要逐行重新定义数据,不灵活,不推荐
func (ctx *UserService) ExportUserListBySlice() {
	requestKey := common.GetYmdHis() + "_" + common.RandomString(10)

	count := ctx.GetUserCount()

	//分页查询列表
	pageSize := 100                                            //每页查询多少条
	pageCount := math.Ceil(float64(count) / float64(pageSize)) //总页数
	//fmt.Println("总页数:", pageCount)
	for page := 1; page <= int(pageCount); page++ {
		dataList := ctx.GetUserList(page, pageSize)
		//给Sheet1赋值
		var excelData [][]string
		for k, v := range dataList {
			//fmt.Println(k, v.ID, v.Name)
			item := []string{
				fmt.Sprintf("%03d", k), //key前面补两个0,要不然反转的时候会按照字符串顺序排序,导致"2>10".这样改后就是"10>02"
				strconv.FormatInt(v.ID, 10),
				v.Name,
				strconv.FormatInt(v.Age, 10),
			}
			excelData = append(excelData, item)
		}

		funcUtils.ReverseTwoDimSlice(excelData)                     //倒序排列,必须保证第0个元素是 key 值
		excelData = funcUtils.DeleteTwoDimSliceFirstChar(excelData) //删除第0个元素(key值)
		pageDiff := int(pageCount) - page + 1

		//导出Excel文件
		fileName, err1 := excelUtils.WriteExcel(excelData, requestKey, fmt.Sprintf("用户数据导出_page_%s", fmt.Sprintf("%04d", pageDiff)))
		if err1 != nil {
			fmt.Println("Write excel error: ", err1)
			os.Exit(1)
		}

		fmt.Println("Write excel success, file name is: ", fileName)
	}

	//导出表头,需要和上面的值保持一一对应
	var excelDataTitle [][]string
	item := []string{
		"ID",
		"姓名",
		"年龄",
	}
	excelDataTitle = append(excelDataTitle, item)
	excelUtils.WriteExcel(excelDataTitle, requestKey, "用户数据导出_page_0000")

	os.Exit(1)
}
